package com.gitee.wsl.android.ext.math

import android.content.res.Resources
import android.view.animation.Interpolator
import android.graphics.PointF
import android.util.TypedValue
import com.gitee.wsl.ext.math.Dimensions
import kotlin.math.abs
import kotlin.math.cos
import kotlin.math.hypot
import kotlin.math.sin


/**
 * Maps t from one range to another range.
 * @param t The value to map.
 * @param fromMin The lower bound of the range that t is being mapped from.
 * @param fromMax The upper bound of the range that t is being mapped from.
 * @param toMin The lower bound of the range that t is being mapped to.
 * @param toMax The upper bound of the range that t is being mapped to.
 * @return The mapped value of t.
 */
fun Dimensions.mapToRange(
    t: Float, fromMin: Float, fromMax: Float, toMin: Float, toMax: Float,
    interpolator: Interpolator
): Float {
    if (fromMin == fromMax || toMin == toMax) {
        //Log.e(TAG, "mapToRange: range has 0 length")
        return toMin
    }
    val progress = Dimensions.getProgress(t, fromMin, fromMax)
    return Dimensions.mapRange(interpolator.getInterpolation(progress), toMin, toMax)
}

/** Bounds t between a lower and upper bound and maps the result to a range.  */
fun Dimensions.mapBoundToRange(
    t: Float, lowerBound: Float, upperBound: Float,
    toMin: Float, toMax: Float, interpolator: Interpolator
): Float {
    return mapToRange(
        Dimensions.boundToRange(t, lowerBound, upperBound), lowerBound, upperBound,
        toMin, toMax, interpolator
    )
}

// 求两点中点
fun Dimensions.center(p1: PointF, p2: PointF): PointF {
    return PointF((p1.x + p2.x) / 2, (p1.y + p2.y) / 2)
}

// 求两点间距离
fun Dimensions.distance(p1: PointF, p2: PointF): Float {
    val dx = abs(p2.x - p1.x)
    val dy = abs(p2.y - p1.y)
    return hypot(dx, dy)
}

// 是否和当前点相近

fun Dimensions.isNearlyPoint(touchX: Float, touchY: Float, point: PointF, minLength: Int): Boolean {
    return distance(PointF(touchX,touchY),point)<minLength
}

// 平移点
fun Dimensions.translate(p: PointF, x: Float, y: Float): PointF {
    return PointF(p.x + x, p.y + y)
}


// 计算两点连线中的一点，这个点把这条线分成两段，比例是percent
fun Dimensions.percent(p1: PointF, p2: PointF, percent: Float): PointF {
    return percent(p1, percent, p2, percent)
}
@JvmName("percent1")
fun Dimensions.percent(p1: PointF, percent1: Float, p2: PointF, percent2: Float): PointF {
    val x = (p2.x - p1.x) * percent1 + p1.x
    val y = (p2.y - p1.y) * percent2 + p1.y
    return PointF(x, y)
}

fun Dimensions.moveTo(angle: Float, length: Float = 1f): PointF {
    return PointF( length * cos(angle),  length * sin(angle))
}
@JvmName("moveTo1")
fun Dimensions.moveTo(basePoint: PointF, angle: Float, length: Float = 1f): PointF {
    return PointF(basePoint.x + length * cos(angle), basePoint.y + length * sin(angle))
}

/*
fun PointF.percent(p2:PointF,percent: Float) = percent(this,p2, percent)

fun PointF.distance( p2: PointF): Float {
    return distance(this,p2)
}

fun PointF.center( p2: PointF): PointF {
    return center(this,p2)
}*/

//斜率
fun PointF.slope( p2: PointF): Float {
    return (p2.y - y) / (p2.x - x)
}

/*fun PointF.moveTo(angle: Float, length: Float = 1f) {
    x += length * cos(angle)
    y += length * sin(angle)
}*/

/**
 * 由 角度 长度 算下一点
 */
fun PointF.relative(angle: Float, length: Float = 1f) = Dimensions.moveTo(this,angle, length)


fun PointF.addWithScalarMultiply(other: PointF, scalar: Float){
    this.x += other.x * scalar
    this.y += other.y * scalar
}





inline val Int.dp: Int
    get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), Resources.getSystem().displayMetrics).toInt()

inline val Long.dp: Long
    get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), Resources.getSystem().displayMetrics).toLong()

inline val Double.dp: Float get() = toFloat().dp

inline val Float.dp: Float
    get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, Resources.getSystem().displayMetrics)

inline val Int.sp: Int
    get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, this.toFloat(), Resources.getSystem().displayMetrics).toInt()

inline val Long.sp: Float
    get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, this.toFloat(), Resources.getSystem().displayMetrics).toFloat()

inline val Double.sp: Float get() = toFloat().sp

inline val Float.sp: Float
    get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, this, Resources.getSystem().displayMetrics)


/**
 * px to dp；将像素值转换为 Density-independent pixel
 */
fun Int.pxToDp() = this.toFloat().pxToDp().toInt()

/**
 * px to dp；将像素值转换为 Density-independent pixel
 */
fun Double.pxToDp() = this.toFloat().pxToDp().toDouble()

/**
 * px to dp；将像素值转换为 Density-independent pixel
 */
fun Float.pxToDp() = this.div(com.gitee.wsl.android.ext.displayMetrics.density)

/**
 * px to dp；将像素值转换为 Density-independent pixel
 */
fun Int.dpToPx() = this.toFloat().dpToPx().toInt()

/**
 * px to dp；将像素值转换为 Density-independent pixel
 */
fun Double.dpToPx() = this.toFloat().dpToPx() .toDouble()

/**
 * px to dp；将像素值转换为 Density-independent pixel
 */
fun Float.dpToPx() = this * com.gitee.wsl.android.ext.displayMetrics.density


/**
 * px to sp；将像素值转换为 Scale-independent pixel
 */
fun Int.pxToSp() = this.toFloat().pxToSp().toInt()

/**
 * px to sp；将像素值转换为 Scale-independent pixel
 */
fun Double.pxToSp() = this.toFloat().pxToSp().toDouble()

/**
 * px to sp；将像素值转换为 scale-independent pixel
 */
fun Float.pxToSp() = this.div(com.gitee.wsl.android.ext.displayMetrics.scaledDensity)

/**
 * px to pt；将像素值转换为磅值
 */
fun Int.pxToPt() = this.toFloat().pxToPt().toInt()

/**
 * px to pt；将像素值转换为磅值
 */
fun Double.pxToPt() = this.toFloat().pxToPt().toDouble()

/**
 * px to pt；将像素值转换为磅值
 */
fun Float.pxToPt() = this.div(com.gitee.wsl.android.ext.displayMetrics.xdpi).div(1.0f / 72f)

/**
 * px to in；将像素值转换为英寸值
 */
fun Int.pxToIn() = this.toFloat().pxToIn().toInt()

/**
 * px to in；将像素值转换为英寸值
 */
fun Double.pxToIn() = this.toFloat().pxToIn().toDouble()

/**
 * px to in；将像素值转换为英寸值
 */
fun Float.pxToIn() = this.div(com.gitee.wsl.android.ext.displayMetrics.xdpi)

/**
 * px to mm；将像素值转换为毫米值
 */
fun Int.pxToMm() = this.toFloat().pxToMm().toInt()

/**
 * px to mm；将像素值转换为毫米值
 */
fun Double.pxToMm() = this.toFloat().pxToMm().toDouble()

/**
 * px to mm；将像素值转换为毫米值
 */
fun Float.pxToMm() = this.div(com.gitee.wsl.android.ext.displayMetrics.xdpi).div(1.0f / 25.4f)

/**
 * px to vw；将像素值转换为宽度百分比值
 */
fun Int.pxToVw() = this.times(100).div(com.gitee.wsl.android.ext.displayMetrics.widthPixels)

/**
 * px to vw；将像素值转换为宽度百分比值
 */
fun Double.pxToVw() = this.times(100).div(com.gitee.wsl.android.ext.displayMetrics.widthPixels)

/**
 * px to vw；将像素值转换为宽度百分比值
 */
fun Float.pxToVw() = this.times(100F).div(com.gitee.wsl.android.ext.displayMetrics.widthPixels)

/**
 * px to vh；将像素值转换为高度百分比值
 */
fun Int.pxToVh() = this.times(100).div(com.gitee.wsl.android.ext.displayMetrics.heightPixels)

/**
 * px to vh；将像素值转换为高度百分比值
 */
fun Double.pxToVh() = this.times(100).div(com.gitee.wsl.android.ext.displayMetrics.heightPixels)

/**
 * px to vh；将像素值转换为高度百分比值
 */
fun Float.pxToVh() = this.times(100F).div(com.gitee.wsl.android.ext.displayMetrics.heightPixels)
